package main

import (
    "fmt"
    "io"
    "log"
    "math"
    "net/http"
    "strconv"
    "unicode/utf8"
    // "gopl.io/ch3/surface"
)

func main() {
    var f float32 = 16777216 // 1 << 24
    fmt.Println(f)
    fmt.Println(f + 1)
    fmt.Println(f == f+1) // "true"!

    // http.HandleFunc("/", handler)
    // err := http.ListenAndServe("localhost:8080", nil)
    // log.Fatal(err)

    s := "Hello, 世界"
    fmt.Println(len(s))                    // "13"
    fmt.Println(utf8.RuneCountInString(s)) // "9"

    for i := 0; i < len(s); {
        r, size := utf8.DecodeRuneInString(s[i:])
        fmt.Printf("%d\t%c\t%v\n", i, r, size)
        i += size
    }

    for i, r := range "Hello, 世界" {
        fmt.Printf("%d\t%q\t%d\n", i, r, r)
    }

    // "program" in Japanese katakana
    var str = "プログラム"
    fmt.Printf("% x\n", str) // "e3 83 97 e3 83 ad e3 82 b0 e3 83 a9 e3 83 a0"
    r := []rune(str)
    fmt.Printf("%x\n", r) // "[30d7 30ed 30b0 30e9 30e0]"

    fmt.Println(string(r))       // "プログラム"
    fmt.Println(string(1234567)) // "?"

    str = "12345"
    fmt.Println(comma(str))
    fmt.Println(str[:2])
}

// comma inserts commas in a non-negative decimal integer string.
func comma(s string) string {
    n := len(s)
    if n <= 3 {
        return s
    }
    return comma(s[:n-3]) + "," + s[n-3:]
}

func handler(w http.ResponseWriter, r *http.Request) {
    //不加Content-Type，浏览器显示的是svg文件内容，而不是解析显示为图片。
    w.Header().Set("Content-Type", "image/svg+xml")

    err := r.ParseForm()
    if err != nil {
        log.Print(err)
    }
    form := r.Form

    wd := 0
    wdQuery := form["width"]
    if len(wdQuery) > 0 { //必须判断数组是否为空，否则越界崩溃
        wdStr := wdQuery[0]
        wd, err = strconv.Atoi(wdStr)
        if err != nil {
            log.Print(err)
        }
    }

    ht := 0
    htQuery := form["height"]
    if len(htQuery) > 0 { //必须判断数组是否为空，否则越界崩溃
        htStr := htQuery[0]
        ht, err = strconv.Atoi(htStr)
        if err != nil {
            log.Print(err)
        }
    }

    stroke := ""
    strokeQuery := form["stroke"]
    if len(strokeQuery) > 0 { //必须判断数组是否为空，否则越界崩溃
        stroke = strokeQuery[0]
    }

    surface(w, wd, ht, stroke)
}

func surface(w io.Writer, wd int, ht int, stroke string) {
    if wd <= 0 {
        wd = width
    }
    if ht <= 0 {
        ht = height
    }
    if len(stroke) == 0 {
        stroke = "grey"
    }
    fmt.Fprintf(w, "<svg xmlns='http://www.w3.org/2000/svg' "+
        "style='stroke: %s; fill: white; stroke-width: 0.7' "+
        "width='%d' height='%d'>", stroke, wd, ht)
    for i := 0; i < cells; i++ {
        for j := 0; j < cells; j++ {
            ax, ay := corner(i+1, j)
            bx, by := corner(i, j)
            cx, cy := corner(i, j+1)
            dx, dy := corner(i+1, j+1)
            fmt.Fprintf(w, "<polygon points='%g,%g %g,%g %g,%g %g,%g'/>\n",
                ax, ay, bx, by, cx, cy, dx, dy)
        }
    }
    fmt.Fprintf(w, "</svg>")
}

func corner(i, j int) (float64, float64) {
    x := xyrange * (float64(i)/cells - 0.5)
    y := xyrange * (float64(j)/cells - 0.5)
    z := f(x, y)

    sx := width/2 + (x-y)*cos30*xyscale
    sy := height/2 + (x+y)*sin30*xyscale - z*zscale
    return sx, sy
}

func f(x, y float64) float64 {
    r := math.Hypot(x, y)
    return math.Sin(r) / r
}
